home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Very Best of Atari Inside
/
The Very Best of Atari Inside 1.iso
/
mint
/
mntlb20
/
lib
/
_divmods.s
< prev
next >
Wrap
Text File
|
1990-04-03
|
3KB
|
94 lines
| long division and modulus routines
|
| written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
|
|
| Revision 1.1, kub 03-90
| first version, replaces the appropriate routine from fixnum.s.
| Should be faster in more common cases. Division is done by 68000 divu
| operations if divisor is only 16 bits wide. Otherwise the normal division
| algorithm as described in various papers takes place. The division routine
| delivers the quotient in d0 and the remainder in d1, thus the implementation
| of the modulo operation is trivial. We gain some extra speed by inlining
| the division code here instead of calling __udivsi3.
.text
.even
.globl __divsi3, ___divsi3
.globl __modsi3, ___modsi3
__divsi3:
___divsi3:
movel d2,a0 | save registers
movel d3,a1
clrw sp@- | sign flag
clrl d0 | prepare result
movel sp@(10),d2 | get divisor
beq 9f | divisor = 0 causes a division trap
bpl 0f | divisor < 0 ?
negl d2 | negate it
notw sp@ | remember sign
0: movel sp@(6),d1 | get dividend
bpl 0f | dividend < 0 ?
negl d1 | negate it
notw sp@ | remember sign
0:
|== case 1) divident < divisor
cmpl d2,d1 | is divident smaller then divisor ?
bcs 8f | yes, return immediately
|== case 2) divisor has <= 16 significant bits
tstw sp@(10)
bne 2f | divisor has only 16 bits
movew d1,d3 | save dividend
clrw d1 | divide dvd.h by dvs
swap d1
beq 0f | (no division necessary if dividend zero)
divu d2,d1
0: movew d1,d0 | save quotient.h
swap d0
movew d3,d1 | (d0.h = remainder of prev divu)
divu d2,d1 | divide dvd.l by dvs
movew d1,d0 | save quotient.l
clrw d1 | get remainder
swap d1
bra 8f | and return
|== case 3) divisor > 16 bits (corollary is dividend > 16 bits, see case 1)
2:
moveq #31,d3 | loop count
3:
addl d1,d1 | shift divident ...
addxl d0,d0 | ... into d0
cmpl d2,d0 | compare with divisor
bcs 0f
subl d2,d0 | big enough, subtract
addw #1,d1 | and note bit into result
0:
dbra d3,3b
exg d0,d1 | put quotient and remainder in their registers
8:
tstw sp@(6) | must the remainder be corrected ?
bpl 0f
negl d1 | yes, apply sign
| the following line would be correct if modulus is defined as in algebra
| addl sp@(6),d1 | algebraic correction: modulus can only be >= 0
0: tstw sp@+ | result should be negative ?
bpl 0f
negl d0 | yes, negate it
0:
movel a1,d3
movel a0,d2
rts
9:
divu d2,d1 | cause division trap
bra 8b | back to user
__modsi3:
___modsi3:
movel sp@(8),sp@- | push divisor
movel sp@(8),sp@- | push dividend
jbsr __divsi3
addql #8,sp
movel d1,d0 | return the remainder in d0
rts